#include "Socket.hpp"
#include <iostream>

#include <memory>
#include <sys/wait.h>
#include <functional>
using namespace SocketModule;
using namespace LogModule;

using ioservice_t = std::function<void(std::shared_ptr<Socket> &sock, InetAddr &client)>;
// 主要解决：链接的问题、IO通信的问题
// 细节：TcpServer，需不需要关心自己未来传递的信息是什么呢？不需要关心的

// 网络版本的计算器，长服务
class TcpServer
{
public:
    TcpServer(uint16_t port)
        : _port(port), _listensock(std::make_unique<TcpSocket>()), _isrunning(false)
    {
        _listensock->BuildTcpSocketMethod(_port); // 创建监听套接字
    }
    void Start(ioservice_t callback)//将回调函数传递给TcpServer，我们要处理什么类型的服务要说清楚
    {
        _isrunning = true;
        while (_isrunning)
        {
            InetAddr cilent; // 客户端
                             // 1、和客户端通信的sockfd
            // 2、客户端对应的网络地址

            auto sock = _listensock->Accept(&cilent); // 获取新链接

            if (sock == nullptr)
            {
                continue;
            }
            LOG(LogLevel::DEBUG) << "accept is running..."<<cilent.StringAddr();
            // sock&&client 客户端的套接字和客户端的身份地址就有了

            pid_t id = fork(); // 创建子进程
            if (id < 0)
            {
                LOG(LogLevel::FATAL) << " fork error";
                //excepter(sock);
                exit(FORK_ERROR);
            }
            else if (id == 0)
            {
                // 子进程处理客户端的请求
                _listensock->Close(); // 关闭监听套接字
                if (fork() > 0)
                {
                    exit(OK); // 父进程退出
                }
                // 孙子进程在处理任务，已经是孤儿了，后续会被会系统进行回收的
                callback(sock, cilent); // 处理客户端的请求
                sock->Close();//关闭套接字
                exit(OK);
            }
            else
            {
                // 父进程->sock
                sock->Close();                       // 关闭套接字
                pid_t rid = ::waitpid(id, nullptr, 0); // 等待子进程结束
                (void)rid;
            }
        }
        _isrunning = false;
    }
    ~TcpServer()
    {
    }

private:
    uint16_t _port; // 端口号

    std::unique_ptr<Socket> _listensock; // 监听套接字

    bool _isrunning; // 服务器是否运行

    //func_t excepter;//服务器异常的回调

};